import ast
from datetime import time
from time import sleep
from typing import Text, Dict

import requests

from utils.other_tools.models import TestCase, RequestType
from utils.read_files_tools.regular_control import cache_regular
from utils.request_tool.dependent_case import DependentCase


class RequestControl:
    def __init__(self, yaml_case):
        self.__yaml_case = TestCase(**yaml_case)

    @classmethod
    def check_headers_str_null(cls, headers):
        headers = ast.literal_eval(cache_regular(str(headers)))
        if headers is None:
            headers = {"headers": None}
        else:
            for key, value in headers.items():
                if not isinstance(value, str):
                    headers[key] = str(value)
        return headers

    def request_type_for_json(self, headers: Dict, method: Text, **kwargs):
        _headers = self.check_headers_str_null(headers)
        _data = self.__yaml_case.data
        _url = self.__yaml_case.url
        res = requests.request(
            method=method,
            url=cache_regular(str(_url)),
            json=ast.literal_eval(cache_regular(str(_data))),
            data={},
            headers=_headers,
            verify=None,
            **kwargs
        )
        return res

    def request_type_for_params(self, headers: Dict, method: Text, **kwargs):
        _data = self.__yaml_case.data
        url = self.__yaml_case.url
        if _data is not None:
            params_data = "?"
            for key, value in _data.items():
                if value is None or value == "":
                    params_data = params_data + key + "=" + key + "&"
                else:
                    params_data = params_data + "&" + key + "=" + key + "&" + value + "&"
            url = self.__yaml_case.url + params_data[:-1]
        _headers = self.check_headers_str_null(headers)
        res = requests.request(
            method=method,
            url=cache_regular(url),
            headers=_headers,
            verify=False,
            data={},
            params=None,
            **kwargs
        )
        return res

    def request_type_for_data(self):
        pass

    def request_type_for_file(self):
        pass

    def request_type_for_none(self, headers: Dict, method: Text, **kwargs):
        _headers = self.check_headers_str_null(headers)
        _url = self.__yaml_case.url
        res = requests.request(
            method=method,
            url=cache_regular(_url),
            headers=_headers,
            verify=False,
            params=None,
            **kwargs
        )
        return res

    def request_type_for_export(self):
        pass

    def http_request(self, dependent_switch=True, **kwargs):
        requests_type_mapping = {
            RequestType.JSON.value: self.request_type_for_json,
            RequestType.PARAMS.value: self.request_type_for_params,
            RequestType.DATA.value: self.request_type_for_data,
            RequestType.FILE.value: self.request_type_for_file,
            RequestType.NONE.value: self.request_type_for_none,
            RequestType.EXPORT.value: self.request_type_for_export,
        }

        is_run = ast.literal_eval(cache_regular(str(self.__yaml_case.is_run)))
        if is_run is True or is_run is None:
            if dependent_switch is True:
                DependentCase(self.__yaml_case).get_dependent_data()

            res = requests_type_mapping.get(self.__yaml_case.request_type)(
                headers=self.__yaml_case.headers,
                method=self.__yaml_case.method,
                **kwargs
            )

            if self.__yaml_case.sleep is not None:
                sleep(self.__yaml_case.sleep)

            _res_data = self._check_params(res=res, yaml_data=self.__yaml_case)

            return _res_data